import org.antlr.v4.runtime.tree.ParseTreeProperty;
import 抽象语法树节点.*;
import 抽象语法树节点.后缀表达式.*;
import 抽象语法树节点.字面量类.*;
import 抽象语法树节点.表达式类.*;
import 抽象语法树节点.语句类.*;

import java.util.ArrayList;

public class Cymbol语言访问器 extends CymbolBaseVisitor<抽象语法树> {

    @Override
    public 抽象语法树 visitCompilationUnit(CymbolParser.CompilationUnitContext ctx) {
        var 结果 = new 编译单元();
        结果.定义 = new ArrayList<>();
        for (var child : ctx.children) {
            结果.定义.add(visit(child));
        }

        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitClassDeclaration(CymbolParser.ClassDeclarationContext ctx) {
        var 结果 = new 类定义(ctx.ID().getSymbol());
        结果.成员 = new ArrayList<>();

        if (ctx.superClass() != null) {
            结果.父类 = (父类) visit(ctx.superClass());
        }

        for (var member : ctx.classMember()) {
            结果.成员.add(visit(member));
        }

        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitSuperClass(CymbolParser.SuperClassContext ctx) {
        return new 父类(ctx.ID().getSymbol()).记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitMethodDeclaration(CymbolParser.MethodDeclarationContext ctx) {
        var 结果 = new 方法定义(ctx.ID().getSymbol());

        结果.返回值类型 = (类型引用) visit(ctx.type());

        if (ctx.formalParameters() != null) {
            结果.参数列表 = (参数列表) visit(ctx.formalParameters());
        }

        结果.代码块 = (代码块) visit(ctx.block());

        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitType(CymbolParser.TypeContext ctx) {
        if (ctx.ID() != null) {
            return new 类型引用(ctx.ID().getSymbol()).记录Token范围(ctx);
        } else {
            return new 类型引用(ctx.primitiveType().start).记录Token范围(ctx);
        }
    }

    @Override
    public 抽象语法树 visitFormalParameters(CymbolParser.FormalParametersContext ctx) {
        var 结果 = new 参数列表();
        结果.参数 = new ArrayList<>();

        for (var parameter : ctx.parameter()) {
            结果.参数.add(visit(parameter));
        }

        return 结果.记录Token范围(ctx);
    }


    @Override
    public 抽象语法树 visitVarParam(CymbolParser.VarParamContext ctx) {
        var 结果 = new 变量定义(ctx.ID().getSymbol());
        结果.类型 = (类型引用) visit(ctx.type());
        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitArrayParam(CymbolParser.ArrayParamContext ctx) {
        var 结果 = new 指针定义(ctx.ID().getSymbol());
        结果.类型 = (类型引用) visit(ctx.type());
        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitPointerParam(CymbolParser.PointerParamContext ctx) {
        var 结果 = new 指针定义(ctx.ID().getSymbol());
        结果.类型 = (类型引用) visit(ctx.type());
        return 结果.记录Token范围(ctx);
    }


    @Override
    public 抽象语法树 visitBlock(CymbolParser.BlockContext ctx) {
        var 结果 = new 代码块();
        结果.语句 = new ArrayList<>();
        if (ctx.statement() != null) {
            for (var statement : ctx.statement()) {
                结果.语句.add(visit(statement));
            }
        }

        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitVarDecl(CymbolParser.VarDeclContext ctx) {
        var 结果 = new 变量定义(ctx.ID().getSymbol());
        结果.类型 = (类型引用) visit(ctx.type());
        if (ctx.expression() != null) {
            结果.初始值 = visit(ctx.expression());
        }

        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitArrayDecl(CymbolParser.ArrayDeclContext ctx) {
        var 结果 = new 指针定义(ctx.ID().getSymbol());
        结果.类型 = (类型引用) visit(ctx.type());
        if (ctx.expression() != null) {
            结果.初始值 = visit(ctx.expression());
        }

        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitPointerDecl(CymbolParser.PointerDeclContext ctx) {
        var 结果 = new 指针定义(ctx.ID().getSymbol());
        结果.类型 = (类型引用) visit(ctx.type());
        if (ctx.expression() != null) {
            结果.初始值 = visit(ctx.expression());
        }

        return 结果.记录Token范围(ctx);
    }


    // 语句类


    @Override
    public 抽象语法树 visitBlockStatement(CymbolParser.BlockStatementContext ctx) {
        return visit(ctx.block());
    }

    @Override
    public 抽象语法树 visitVarStatement(CymbolParser.VarStatementContext ctx) {
        return visit(ctx.varDeclaration());
    }

    @Override
    public 抽象语法树 visitIfStatement(CymbolParser.IfStatementContext ctx) {
        var 结果 = new 条件语句();
        结果.条件 = visit(ctx.condition);
        结果.真值语句 = visit(ctx.trueStatement);

        if (ctx.falseStatement != null) {
            结果.假值语句 = visit(ctx.falseStatement);
        }

        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitReturnStatement(CymbolParser.ReturnStatementContext ctx) {
        var 结果 = new 返回语句();

        if (ctx.expression() != null) {
            结果.返回值 = visit(ctx.expression());
        }

        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitAssignStatement(CymbolParser.AssignStatementContext ctx) {
        var 结果 = new 赋值语句();
        结果.左值 = visit(ctx.unaryExpression());
        结果.右值 = visit(ctx.expression());
        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitCallStatement(CymbolParser.CallStatementContext ctx) {
        return visit(ctx.postfixExpression());
    }

    @Override
    public 抽象语法树 visitExpressionList(CymbolParser.ExpressionListContext ctx) {
        var 结果 = new 表达式列表();
        结果.表达式 = new ArrayList<>();

        for (var expression : ctx.expression()) {
            结果.表达式.add(visit(expression));
        }

        return 结果.记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitArithmeticExpression(CymbolParser.ArithmeticExpressionContext ctx) {
        if (ctx.unaryExpression() != null) {
            return visit(ctx.unaryExpression());
        }

        return new 算术表达式(ctx.op.getText(), visit(ctx.arithmeticExpression(0)), visit(ctx.arithmeticExpression(1)))
                .记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitRelationalExpression(CymbolParser.RelationalExpressionContext ctx) {
        if (ctx.unaryExpression() != null) {
            return visit(ctx.unaryExpression());
        }

        return new 关系表达式(ctx.op, visit(ctx.relationalExpression(0)), visit(ctx.relationalExpression(1)))
                .记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitEqualityExpression(CymbolParser.EqualityExpressionContext ctx) {
        if (ctx.unaryExpression() != null) {
            return visit(ctx.unaryExpression());
        }

        return new 匹值表达式(ctx.op, visit(ctx.equalityExpression(0)), visit(ctx.equalityExpression(1)))
                .记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitMinusExpression(CymbolParser.MinusExpressionContext ctx) {
        return new 取负表达式(visit(ctx.unaryExpression())).记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitNotExpression(CymbolParser.NotExpressionContext ctx) {
        return new 取反表达式(visit(ctx.unaryExpression())).记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitAddressExpression(CymbolParser.AddressExpressionContext ctx) {
        return new 取地址表达式(visit(ctx.unaryExpression())).记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitDereferenceExpression(CymbolParser.DereferenceExpressionContext ctx) {
        return new 解引用表达式(visit(ctx.unaryExpression())).记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitCallExpression(CymbolParser.CallExpressionContext ctx) {
        return visit(ctx.postfixExpression());
    }


    // 后缀表达式类


    @Override
    public 抽象语法树 visitPostfixExpression(CymbolParser.PostfixExpressionContext ctx) {
        if (ctx.primary() != null) {
            return visit(ctx.primary());
        }

        var 主表达式 = visit(ctx.postfixExpression());
        标记.put(ctx, 主表达式);
        return visit(ctx.postfix()).记录Token范围(ctx);
    }

    private final ParseTreeProperty<抽象语法树> 标记 = new ParseTreeProperty<>();
    
    @Override
    public 抽象语法树 visitPrimary(CymbolParser.PrimaryContext ctx) {
        if (ctx.ID() != null) {
            return new 标识符(ctx.ID().getSymbol()).记录Token范围(ctx);
        } else if (ctx.INT() != null) {
            return new 整数型字面量(ctx.INT().getSymbol()).记录Token范围(ctx);
        } else if (ctx.FLOAT() != null) {
            return new 浮点型字面量(ctx.FLOAT().getSymbol()).记录Token范围(ctx);
        } else if (ctx.CHAR() != null) {
            return new 字符型字面量(ctx.CHAR().getSymbol()).记录Token范围(ctx);
        } else if (ctx.BOOL() != null) {
            return new 逻辑型字面量(ctx.BOOL().getSymbol()).记录Token范围(ctx);
        } else {
            return visit(ctx.expression());
        }
    }

    @Override
    public 抽象语法树 visitMethodCall(CymbolParser.MethodCallContext ctx) {
        var 主表达式 = 标记.get(ctx.parent);
        
        var 结果 = new 方法调用表达式();
        结果.方法 = 主表达式;
        if (ctx.expressionList() != null) {
            结果.参数 = (表达式列表) visit(ctx.expressionList());
        }

        return 结果;
    }

    @Override
    public 抽象语法树 visitArrayAccess(CymbolParser.ArrayAccessContext ctx) {
        var 主表达式 = 标记.get(ctx.parent);
        var 加法 = new 算术表达式("+", 主表达式, visit(ctx.expression())).记录Token范围(ctx);
        return new 解引用表达式(加法).记录Token范围(ctx);
    }

    @Override
    public 抽象语法树 visitMemberAccess(CymbolParser.MemberAccessContext ctx) {
        var 主表达式 = 标记.get(ctx.parent);
        var 结果 = new 成员访问表达式(ctx.ID().getSymbol());
        结果.对象 = 主表达式;
        return 结果;
    }

    @Override
    public 抽象语法树 visitPointerAccess(CymbolParser.PointerAccessContext ctx) {
        var 主表达式 = 标记.get(ctx.parent);
        var 解引用 = new 解引用表达式(主表达式);
        var 成员访问 = new 成员访问表达式(ctx.ID().getSymbol());
        成员访问.记录Token范围(ctx);
        成员访问.对象 = 解引用;
        return 成员访问.记录Token范围(ctx);
    }
}
